/*
 * echo_server.cpp
 * 
 * 使用 Protobuf + MessageDispatcher 的 Echo 服务器
 * 阶段2实现
 */

#include "protocol/PacketHeader.h"
#include "protocol/MessageCodec.h"
#include "protocol/MessageDispatcher.h"
#include "echo.pb.h"  // 生成的 protobuf 文件在 build 目录

#include <muduo/net/TcpServer.h>
#include <muduo/net/EventLoop.h>
#include <muduo/base/Logging.h>
#include <muduo/base/Timestamp.h>

#include <iostream>
#include <string>

using namespace muduo;
using namespace muduo::net;
using namespace protocol;

class ProtoEchoServer {
public:
    ProtoEchoServer(EventLoop* loop, const InetAddress& listenAddr)
        : server_(loop, listenAddr, "ProtoEchoServer"),
          loop_(loop) {
        // 设置连接回调
        server_.setConnectionCallback(
            std::bind(&ProtoEchoServer::onConnection, this, _1));
        
        // 设置消息回调
        server_.setMessageCallback(
            std::bind(&ProtoEchoServer::onMessage, this, _1, _2, _3));
        
        // 设置线程数
        server_.setThreadNum(4);
        
        // 注册消息处理器（使用 TcpConnection 版本）
        dispatcher_.registerTcpHandler<EchoRequest>(
            MSG_ECHO_REQUEST,
            std::bind(&ProtoEchoServer::onEchoRequest, this, _1, _2, _3));
        
        LOG_INFO << "ProtoEchoServer initialized";
    }

    void start() {
        server_.start();
    }

private:
    // 连接建立/断开回调
    void onConnection(const TcpConnectionPtr& conn) {
        LOG_INFO << "ProtoEchoServer - " << conn->peerAddress().toIpPort() 
                 << " -> " << conn->localAddress().toIpPort() << " is "
                 << (conn->connected() ? "UP" : "DOWN");
    }

    // 消息到达回调
    void onMessage(const TcpConnectionPtr& conn,
                   Buffer* buf,
                   Timestamp time) {
        // 循环处理所有完整的消息包（处理粘包）
        while (buf->readableBytes() >= PacketHeader::kHeaderSize) {
            // 解码消息
            uint16_t msgId;
            std::string data;
            int ret = MessageCodec::decode(buf, msgId, data);
            
            if (ret > 0) {
                // 成功解码一个完整消息
                LOG_DEBUG << "Received message: msgId=" << msgId 
                         << ", size=" << data.size();
                
                // 分发消息（使用 TcpConnection 版本）
                dispatcher_.dispatchTcp(conn, msgId, data, time);
            } else if (ret == 0) {
                // 数据包不完整，等待更多数据
                break;
            } else {
                // 解码错误，关闭连接
                LOG_ERROR << "Decode error, closing connection";
                conn->shutdown();
                break;
            }
        }
    }

    // 处理 Echo 请求
    void onEchoRequest(const TcpConnectionPtr& conn,
                      const EchoRequest& request,
                      Timestamp time) {
        LOG_INFO << conn->name() << " echo request: " << request.message();
        
        // 构造响应
        EchoResponse response;
        response.set_message(request.message());
        response.set_timestamp(time.microSecondsSinceEpoch());
        
        // 编码并发送
        sendMessage(conn, MSG_ECHO_RESPONSE, response);
    }
    
    // 发送 Protobuf 消息
    void sendMessage(const TcpConnectionPtr& conn,
                    uint16_t msgId,
                    const google::protobuf::Message& message) {
        Buffer buf;
        MessageCodec::encode(msgId, message, &buf);
        conn->send(&buf);
    }

    TcpServer server_;
    EventLoop* loop_;
    MessageDispatcher dispatcher_;
};

int main(int argc, char* argv[]) {
    LOG_INFO << "pid = " << getpid();
    
    // 设置端口
    uint16_t port = 8080;
    if (argc > 1) {
        port = static_cast<uint16_t>(atoi(argv[1]));
    }
    
    LOG_INFO << "ProtoEchoServer listening on port " << port;
    
    EventLoop loop;
    InetAddress listenAddr(port);
    ProtoEchoServer server(&loop, listenAddr);
    
    server.start();
    
    LOG_INFO << "Server started, entering event loop";
    loop.loop();
    
    return 0;
}

